#include "image.h"
#include "stb_image/stb_image.h"
#include "stb_image/stb_image_write.h"
#include "math/MathLib.h"

using rtMath::vec4;

Image* Image::CreateFromMemory(void* data, uint32 width, uint32 height, uint32 bitsPerPixel)
{
	void* imageData = data;
	if (!imageData)
		imageData = reinterpret_cast<void*>(new char[width * height * (bitsPerPixel >> 3)]);

	if (!imageData)
		return NULL;

	Image* image = new Image(imageData, width, height, bitsPerPixel);
	return image;
}

Image* Image::CreateFromFile(const rtString& fileName)
{
	int width, height, comp;
	uint8* imageData = stbi_load(fileName.c_str(), &width, &height, &comp, 4);
	if (!imageData)
		return NULL;

	Image* image = new Image(imageData, width, height, comp << 3);
	return image;
}

bool Image::WriteToFile(const rtString& fileName, Image* image)
{
	if (!image || !image->GetDataPtr())
		return false;

	int result = stbi_write_tga(fileName.c_str(), image->GetWidth(), image->GetHeight(), image->GetBitsPerPixel() >> 3, image->GetDataPtr());
	return result != 0;
}




Image::Image(void* data, uint32 width, uint32 height, uint32 bitsPerPixel, int channelType)
	: m_Data(data)
	, m_Width(width)
	, m_Height(height)
	, m_BitsPerPixel(bitsPerPixel)
	, m_ChannelType(channelType)
{
}
Image::Image(const Image& copy)
{
}
Image::~Image()
{
	SafeDeleteArray(m_Data);
}


uint32 Image::GetWidth(void) const
{
	return m_Width;
}

uint32 Image::GetHeight(void) const
{
	return m_Height;
}

uint32 Image::GetBitsPerPixel(void) const
{
	return m_BitsPerPixel;
}

int Image::GetChannelType(void) const
{
	return m_ChannelType;
}

void* Image::GetDataPtr(void)
{
	return m_Data;
}

const void* Image::GetDataPtr(void) const
{
	return m_Data;
}

void Image::SetPixel(uint32 x, uint32 y, const vec4& color)
{
	if (!m_Data || x > m_Width || y > m_Height)
		return;

	switch (m_ChannelType)
	{
		case ChannelTypeUchar:
		{
			uint8* dataPtr = reinterpret_cast<uint8*>(m_Data);
			const int numChannels = m_BitsPerPixel / (sizeof(uint8) << 3);
			const uint32 colorUint = rtMath::vec4_to_uint32(color);

			uint8* pixelAddress = dataPtr + ((x + y * m_Width) * numChannels);
			pixelAddress[0] = (colorUint >> 24) & 0xff;
			pixelAddress[1] = (colorUint >> 16) & 0xff;
			pixelAddress[2] = (colorUint >>  8) & 0xff;
			if (numChannels == 4)
				pixelAddress[3] = colorUint & 0xff;
		} break;

		case ChannelTypeFloat:
		{
			float* dataPtr = reinterpret_cast<float*>(m_Data);
			const int numChannels = m_BitsPerPixel / (sizeof(float) << 3);

			float* pixelAddress = dataPtr + ((x + y * m_Width) * numChannels);
			pixelAddress[0] = color.r;
			pixelAddress[1] = color.g;
			pixelAddress[2] = color.b;
			if (numChannels == 4)
				pixelAddress[3] = color.a;
		} break;
	}
}

const vec4 Image::GetPixel(uint32 x, uint32 y) const
{
	return vec4();
}
